import type { Rules } from './validator';
import type { ComponentType, Localdata } from './index';
import { type FormItem } from './formItem';
import type { ExtractPropTypes, Ref } from 'vue';
import { basicProps } from '../props';
import type { IsInternalInterfaceEnum } from '@/enums/formEnum';
import type { UseUploadOptions } from '@/hooks/core/useUpload';

export interface RenderCallbackParams {
  schema: FormSchema;
  values: Recordable;
  model: Recordable;
  field: string;
  setFormModel?: (obj: { field: string, value: any }) => void
}

export type FormInteractionMode = 'normal' | 'details' | 'edit';

export type FormProps = ExtractPropTypes<typeof basicProps>

export interface FormActionType {
  /**
   * 提交表单
   */
  submit: () => Promise<void>;

  /**
   * 设置表单字段值
   */
  setFieldsValue: (values: Recordable) => Promise<void>;

  /**
   * 重置表单值
   */
  resetFields: () => Promise<void>;

  /**
   * 获取表单值
   */
  getFieldsValue: () => Recordable;

  /**
   * 清空校验
   */
  clearValidate: (name?: string | string[]) => Promise<void>;

  /**
   * 更新表单的 schema, 只更新函数所传的参数
   */
  updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
  resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
  /**
   * 获取所有 schema
   */
  getSchemas: () => Promise<FormSchema[]>;
  /**
   * 设置表单 Props
   */
  setProps: (formProps: Partial<FormProps>) => Promise<void>;

  /**
   *  根据 field 删除 Schema
   */
  removeSchemaByFiled: (field: string | string[]) => Promise<void>;

  /**
   * 插入到指定 filed 后面，如果没传指定 field，则插入到最后,当 first = true 时插入到第一个位置
   */
  appendSchemaByField: (schema: FormSchema, prefixField?: string, first?: boolean) => Promise<void>;

  /**
   * 校验整个表单
   */
  validate: (nameList?: string | string[]) => Promise<any>;

  /**
   * 滚动到对应字段位置
   */
  scrollToField: (name: string) => Promise<void>;
}

export type RegisterFn = (formInstance: FormActionType) => void;

/** loacldata 字段映射 */
export type localDataMapping = (
  resData: any[],
  map: { label: string; value: string },
) => Localdata[];

export type UseFormReturnType = [RegisterFn, FormActionType];

/**
 *  @property {String }	type	输入框的类型（默认text）
 * 	@value text			文本输入键盘
 * 	@value textarea	多行文本输入键盘
 * 	@value password	密码输入键盘
 * 	@value number		数字输入键盘，注意iOS上app-vue弹出的数字键盘并非9宫格方式
 * 	@value idcard		身份证输入键盘，微信、支付宝、百度、QQ小程序
 * 	@value digit		带小数点的数字键盘	，App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持
 */
export type FormInputType =
  'text' | 'textarea' | 'password' | 'number' | 'idcard' | 'digit' | 'nickname'


export interface ComponentProps {
  placeholder?: string
  limit?: number
  min?: number
  localdata?: Localdata[] | Ref<Localdata[]>
  schema?: FormSchema;
  maxlength?: number
  showWordLimit?: boolean
  isCrop?: UseUploadOptions['isCrop'],
  cropOptions?: UseUploadOptions['cropOptions'],
  /** 省市区街道的启用数量 */
  enableValue?: number
  /** 后管设置的默认值(同content) */
  itemDefault?: any
  inputType?: FormInputType
  /** 是否显示快捷获取手机号码按钮 */
  showGetPhone?: boolean
  /** 是否多选 */
  multiple?: boolean
}

export interface FormSchema {
  // 字段名
  field: string;

  // 标签名
  label?: string;

  // 覆盖统一设置的 labelWidth
  labelWidth?: string | number;

  // 覆盖统一设置的 labelAlign
  labelAlign?: 'left' | 'center' | 'top';

  // 组件类型
  component: ComponentType;

  // 所渲染的组件的 props
  componentProps?: ((opt: {
    schema?: FormSchema;
    formActionType?: FormActionType;
    formModel?: Recordable;
  }) => Recordable) | object | ComponentProps

  // 校验规则
  rules?: Rules[];

  // 数据库中, 数据映射唯一标识
  dataType?: string;

  // 控件数据来源
  isInternalInterface?: IsInternalInterfaceEnum,

  // form-item props
  itemProps?: Partial<FormItem>;

  // 校验信息是否加入 label
  rulesMessageJoinLabel?: boolean;

  // 简化 rules 配置，为 true 则转化成 [{required:true}]
  required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

  // 默认值
  defaultValue?: any;

  // 自定义 slot，渲染组件
  slot?: string;

  // 动态判断当前组件是否显示
  ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

  // 动态判断当前组件是否禁用
  dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);

  // 动态判返当前组件你校验规则
  dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rules;

  // 是否捕捉当前项的change事件
  isOnChange?: boolean
}
